/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package co.com.umobile.gui;

import java.net.URI;

import android.app.ActionBar;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import co.com.umobile.R;
import co.com.umobile.application.GlobalState;
import co.com.umobile.common.Numbers;
import co.com.umobile.common.util.ServicesCodes;
import co.com.umobile.common.widget.ProgressHandler;
import co.com.umobile.network.CheckConnection;
import co.com.umobile.persistence.ProviderUtilities;
import co.com.umobile.service.GenericSyncAdapter;
import co.com.umobile.service.LoginServices;
import co.com.umobile.service.NotificationSyncService;
import co.com.umobile.service.PlaceSyncService;
import co.com.umobile.service.SubjectDetailSyncService;
import co.com.umobile.service.SubjectSyncService;
import co.com.umobile.service.UpdateServices;

/**
 * @author sgranada
 * 
 *         23/02/2012
 */
public class UpdatesActivity extends Activity {

	/** the home container. */
	GridView gridViewHome;

	/** the grid views. */
	private View[] listView = new View[Numbers.FOUR];

	/** globalState is used to transfer data to other activity. */
	private GlobalState globalState;

	/** the updateServices services. */
	private UpdateServices updateServices;

	/** the update all button. */
	LinearLayout updateAllbutton;

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.updates_layout);
		gridViewHome = (GridView) findViewById(R.id.gridViewHome);
		updateAllbutton = (LinearLayout) findViewById(R.id.linearUpdateAll);
		afterViews();
	}

	/**
	 * method to be executed after the oncreate.
	 */
	void afterViews() {

		globalState = (GlobalState) getApplication();
		updateServices = globalState.getUpdateServices();

		ActionBar actionBar = getActionBar();
		actionBar.setTitle(R.string.update_screen_title);

		int orientation = getResources().getConfiguration().orientation;

		if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
			gridViewHome.setNumColumns(Numbers.TWO);
		} else {
			gridViewHome.setNumColumns(Numbers.TWO);
		}

		fillViews();
		gridViewHome.setAdapter(new UpdateAdapter());

		updateAllbutton.setVisibility(LinearLayout.VISIBLE);
		updateAllbutton.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				updateAll();
			}
		});

	}

	/**
	 * updates all the entities.
	 */
	private void updateAll() {

		if (updateServices.isAnyServiceRunning(this, globalState)) {

			showDialog(getApplicationContext().getResources().getString(R.string.currently_updating));
		} else if (!CheckConnection.isConnected(getApplicationContext())) {
			showDialog(getApplicationContext().getResources().getString(R.string.update_offline_message));
		} else {

			if (gridViewHome != null && listView != null && listView.length > 0) {

				Integer[] services = ServicesCodes.getServices();
				globalState.getUpdateQueue().clear();

				for (int i = 0; i < services.length; i++) {
					int currentCode = services[i];

					View view = listView[i];

					final TextView descriptionTextView = ((TextView) view.findViewById(R.id.textViewUpdateMessage));
					final ProgressBar progressBar = ((ProgressBar) view.findViewById(R.id.progressBarUpdate));
					final ImageView statusIcon = ((ImageView) view.findViewById(R.id.update_status_icon));

					ProgressHandler handler = new ProgressHandler(UpdatesActivity.this, progressBar,
							descriptionTextView, statusIcon, ServicesCodes.getIdNameById(currentCode), currentCode,
							ProviderUtilities.getUriByServiceCode(currentCode));
					globalState.getHandlerByService().put(currentCode, handler);

					globalState.getUpdateQueue().add(currentCode);

				}

				Intent intentSync = new Intent(GenericSyncAdapter.SYNC_INIT);
				sendBroadcast(intentSync);

			}

		}
	}

	/**
	 * fill the views.
	 */
	private void fillViews() {

		listView[0] = getUpdateItemView(R.string.subject_label, 0, SubjectSyncService.class.getName(),
				ServicesCodes.SUBJECT_UPDATE, ProviderUtilities.CONTENT_URI_SUBJECT);
		listView[1] = getUpdateItemView(R.string.place_label, 1, PlaceSyncService.class.getName(), 1,
				ProviderUtilities.CONTENT_URI_PLACE);
		listView[2] = getUpdateItemView(R.string.details_subject_label, 2, SubjectDetailSyncService.class.getName(),
				ServicesCodes.SUBJECT_DETAIL_UPDATE, ProviderUtilities.CONTENT_URI_SUBJECT_DETAIL);
		listView[3] = getUpdateItemView(R.string.notification_label, 3, NotificationSyncService.class.getName(), ServicesCodes.NOTIFICATION_UPDATE,
				ProviderUtilities.CONTENT_URI_NOTIFICATION);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		switch (item.getItemId()) {
		case android.R.id.home:
			finish();
			break;
		default:
			return super.onOptionsItemSelected(item);
		}

		return true;
	}

	/**
	 * creates an update item view.
	 * 
	 * @param titleId
	 *            title id.
	 * @param position
	 *            position to set.
	 * @param className
	 *            Class name.
	 * @param serviceCode
	 *            service code.
	 * @param serviceUri
	 *            service {@link URI}.
	 * @return {@link View}.
	 */
	private View getUpdateItemView(final int titleId, final int position, String className, final int serviceCode,
			final Uri serviceUri) {

		View view = getLayoutInflater().inflate(R.layout.update_item_layout, null);
		((TextView) view.findViewById(R.id.textViewUpdateTitle)).setText(titleId);

		initView(view, titleId, serviceCode, serviceUri);

		checkService(className, ((ProgressBar) view.findViewById(R.id.progressBarUpdate)),
				((TextView) view.findViewById(R.id.textViewUpdateMessage)), titleId, serviceCode, serviceUri);

		return view;

	}

	/**
	 * init the layout view.
	 * 
	 * @param view
	 *            {@link View}.
	 * @param titleId
	 *            title Id.
	 * @param serviceCode
	 *            Service code.
	 * @param serviceUri
	 *            Service {@link URI}.
	 */
	private void initView(View view, final int titleId, final int serviceCode, final Uri serviceUri) {

		final TextView descriptionTextView = ((TextView) view.findViewById(R.id.textViewUpdateMessage));

		final ProgressBar progressBar = ((ProgressBar) view.findViewById(R.id.progressBarUpdate));

		final ImageView statusIcon = ((ImageView) view.findViewById(R.id.update_status_icon));

		Button buttonUpdate = ((Button) view.findViewById(R.id.buttonUpdate));

		buttonUpdate.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				if (updateServices.isAnyServiceRunning(UpdatesActivity.this, globalState)) {

					showDialog(getApplicationContext().getResources().getString(R.string.currently_updating));
				} else if (!CheckConnection.isConnected(getApplicationContext())) {
					showDialog(getApplicationContext().getResources().getString(R.string.update_offline_message));
				} else {

					ProgressHandler handler = new ProgressHandler(UpdatesActivity.this, progressBar,
							descriptionTextView, statusIcon, titleId, serviceCode, serviceUri);
					globalState.getHandlerByService().put(serviceCode, handler);

					globalState.getUpdateQueue().clear();
					globalState.getUpdateQueue().add(serviceCode);

					Intent intentSync = new Intent(GenericSyncAdapter.SYNC_INIT);
					sendBroadcast(intentSync);

				}

			}
		});

	}

	/**
	 * checks if a service is running and starts the progress bar and text view.
	 * 
	 * @param serviceName
	 *            service name.
	 * @param progressbar
	 *            {@link ProgressBar}.
	 * @param textView
	 *            {@link TextView}.
	 * @param titleId
	 *            Title id.
	 * @param serviceCode
	 *            service code.
	 * @param serviceUri
	 *            service {@link Uri}.
	 */
	private void checkService(String serviceName, ProgressBar progressbar, TextView textView, final int titleId,
			final int serviceCode, final Uri serviceUri) {

		if (isServiceRunning(serviceName, serviceCode)) {

			if (globalState != null && globalState.getHandlerByService() != null
					&& globalState.getHandlerByService().get(serviceCode) != null) {

				globalState.getHandlerByService().get(serviceCode).setProgressBar(progressbar);
				globalState.getHandlerByService().get(serviceCode).setLabel(textView);

			}

		}
	}

	@Override
	public void onAttachedToWindow() {
		super.onAttachedToWindow();
		Window window = getWindow();
		window.setFormat(PixelFormat.RGBA_8888);
		window.addFlags(WindowManager.LayoutParams.FLAG_DITHER);
	}

	/**
	 * checks if a service is running.
	 * 
	 * @param className
	 *            Class name.
	 * @param serviceCode
	 *            Service code.
	 * @return boolean indicating if some service is running.
	 */
	public boolean isServiceRunning(String className, Integer serviceCode) {
		ActivityManager manager = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
		for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
			String serviceClassName = service.service.getClassName();
			if (className.equals(serviceClassName)) {
				return true;
			}
		}

		if (globalState != null && globalState.getHandlerByService() != null
				&& globalState.getHandlerByService().containsKey(serviceCode)) {
			return true;
		}

		return false;
	}

	/**
	 * This method shows a custom dialog displaying the message given as a parameter.
	 * 
	 * @param message
	 *            Message to show.
	 */
	public void showDialog(String message) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(message)
				.setCancelable(false)
				.setPositiveButton(getApplicationContext().getResources().getString(R.string.ok_button),
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {
								dialog.cancel();
							}
						});

		AlertDialog alertDialog = builder.create();
		alertDialog.setOwnerActivity(this);
		alertDialog.show();
	}

	/**
	 * the updates item adapter.
	 * 
	 * @author sgranada
	 * @since 24/02/2012
	 */
	public class UpdateAdapter extends BaseAdapter {

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.widget.Adapter#getCount()
		 */
		public int getCount() {
			return listView.length;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.widget.Adapter#getItem(int)
		 */
		public Object getItem(int position) {
			return position;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.widget.Adapter#getItemId(int)
		 */
		public long getItemId(int position) {
			return position;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)
		 */
		public View getView(int position, View convertView, ViewGroup parent) {
			return listView[position];
		}

	}

}
